<?php
/**
*
* Utility class for casting variable values
*
* @package WKernel
*/
class WK_VarFilter {
  private $rules;
  
  protected $built_in_rules = array(
    'request' => array('*' => 'autoCast')
  );
  
  /**
  * Rules format:
  * <pre>
  * [namespace]
  * var_name = filter_method
  * <pre>
  * @parameter string $rules_file path tothe ini-file with filtering rules
  */
  public function __construct($rules_file){
  	$rules = @file_get_contents($rules_file, true);
    if(empty($rules_file) || empty($rules))
      $this->rules = array();
    else
      $this->rules = parse_ini_file($rules_file, true);
    foreach($this->built_in_rules as $ns => $rules){
      if(empty($this->rules[$ns])) 
        $this->rules[$ns] = $rules;
      else
        $this->rules[$ns] = array_merge($this->rules[$ns], $rules);
    }
  }
  
  /**
  * Applying filter
  * 
  * @parameter string $ns namespace of the variable
  * @parameter string $name name of the variable
  * @parameter mixed $value the value
  */
  public function filter($ns, $name, $value){
    $callbacks = array();
    $callbacks[] = @$this->rules[$ns]['*'];
    $callbacks[] = @$this->rules[$ns][$name];
    foreach($callbacks as $callback) {
      if(!empty($callback) && method_exists($this, $callback)) {
        $value = call_user_func(array($this, $callback), $value);
      }
    }
    return $value;    
  }
  private function autoCast($value){
    if(is_numeric($value)) 
      return $this->toNumber($value);
    elseif(in_array($value, array('yes', 'no', 'true', 'false')))
      return $this->toBoolean($value);
    else
      return $value;
  }
  //TODO: take in account format of a decimal separators
  private function toNumber($value){
    if(is_numeric($value)){
      if(strpos($value, '.') !== false)
        $value = floatval($value);
      else
        $value = intval($value);
    }
    else 
      $value = 0;
    return $value;
  }
  private function toBoolean($value){
    switch($value){
      case 'true' : $value = true; break;
      case 'yes'  : $value = true; break;
      case 'false': $value = false; break;
      case 'no'   : $value = false; break;
    }
    return $value ? true : false;
  }
}